home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!ames!mailrus!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
- From: mjy@sdti.sdti.com (Michael J. Young)
- Newsgroups: comp.sources.misc
- Subject: v05i066: Program to Display Memory Allocation in System V
- Message-ID: <341@sdti.SDTI.COM>
- Date: 3 Dec 88 00:36:04 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: mjy@sdti.sdti.com (Michael J. Young)
- Organization: Software Development Technologies, Sudbury MA
- Lines: 722
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 5, Issue 66
- Submitted-by: "Michael J. Young" <mjy@sdti.sdti.com>
- Archive-name: mapmem
-
- Mapmem displays a visual map of physical memory and swap device allocation
- for System V Unix. The map is updated at 1 second intervals, providing a
- real-time view of system memory utilization.
-
- I'm sure there are lots of utilities out there that do things like this,
- but I don't have them here. I hope someone else finds it useful as well.
-
- Please send bug reports/fixes, etc., to me.
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: Makefile README mapmem.8 mapmem.c
- # Wrapped by mjy@sdti on Wed Nov 30 16:04:20 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(733 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X## @(#)$Id: Makefile, V1.1.1.3 88/11/30 16:03:44 $
- X##
- X## MAPMEM makefile
- X## Version : 1.1.1.3 - 88/11/30 16:03:44
- X##
- X
- X## edit as appropriate...
- XCFLAGS = -g -O
- XLDFLAGS =
- XLIBFLAGS = -lcurses
- X
- X## Directory in which executable should be placed:
- XDESTDIR = /usr/local/bin
- X
- X## Directory in which man page should be placed:
- XMANDIR = /usr/man/l_man/man8
- X
- X## MAPMEM must have read access to /dev/kmem. Therefore, it must be
- X## setgid to some group with the appropriate privilege.
- XGRPID = sys
- X
- Xmapmem : mapmem.c
- X $(CC) $(LDFLAGS) $(CFLAGS) -o mapmem mapmem.c $(LIBFLAGS)
- X
- Xinstall: mapmem
- X cp mapmem $(DESTDIR)/mapmem
- X chgrp $(GRPID) $(DESTDIR)/mapmem
- X chmod g+s $(DESTDIR)/mapmem
- X cp mapmem.8 $(MANDIR)/mapmem.8
- X chmod 444 $(MANDIR)/mapmem.8
- END_OF_Makefile
- if test 733 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(501 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- XMAPMEM displays a visual map of physical memory and swap device allocations
- Xfor a swapping (i.e., non-paged) Unix system. The map is updated at 1 second
- Xintervals, providing a real-time indication of system memory utilization.
- X
- XTo install, simply edit the makefile and type 'make'. Typing 'make install'
- Xwill install the executable with the appropriate privileges.
- X
- XMAPMEM requires read access to /dev/kmem, and must therefore be run as
- Xsetgid to some group with the appropriate access (e.g., sys).
- END_OF_README
- if test 501 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f mapmem.8 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"mapmem.8\"
- else
- echo shar: Extracting \"mapmem.8\" \(943 characters\)
- sed "s/^X//" >mapmem.8 <<'END_OF_mapmem.8'
- X.\" @(#)$ mapmem.8, Version 1.1.1.1 - 88/11/28 18:16:51
- X.TH MAPMEM 8
- X.ad b
- X.SH NAME
- Xmapmem \- display map of core and swap allocation.
- X.SH SYNOPSIS
- X.B mapmem
- X[
- X.B \-d #
- X] [
- X.B \-vh?
- X]
- X.SH DESCRIPTION
- X.I Mapmem
- Xdisplays a visual map of physical memory and swap device
- Xallocation of a swapping (i.e., non-paged) Unix system. The map display is
- Xupdated at periodic intervals, providing a real-time indication of system
- Xmemory utilization.
- X.I Mapmem
- Xuses
- X.I curses(3x)
- Xfor its screen output, based on the \fBTERM\fR environment variable.
- X.SH OPTIONS
- X.IP \fB-d#\fR
- XDelay '\fB#\fR' seconds between updates. Defaults to 1 second.
- X.IP \fB-h\fR
- XDisplay a short usage message.
- X.IP \fB-v\fR
- XDisplay version and patch level of
- X.I mapmem .
- X.IP \fB-?\fR
- XSame as \fB-h\fR.
- X.SH BUGS
- XProbably.
- X.SH "SEE ALSO"
- X.I curses(3x) ,
- X.I terminfo(4)
- X.SH AUTHOR
- XMichael J. Young
- X.br
- Xharvard!sdti!mjy
- X.br
- XInternet : mjy@sdti.SDTI.COM
- X.SH VERSION
- X1.1 - 88/11/28 18:16:51
- END_OF_mapmem.8
- if test 943 -ne `wc -c <mapmem.8`; then
- echo shar: \"mapmem.8\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f mapmem.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"mapmem.c\"
- else
- echo shar: Extracting \"mapmem.c\" \(12856 characters\)
- sed "s/^X//" >mapmem.c <<'END_OF_mapmem.c'
- Xstatic char sccsid[] = "@(#)$Id: mapmem.c, V1.1.1.2 88/11/28 18:16:45 $";
- X
- X/*
- X * map.c - display kernel allocation map information
- X * Version : 1.1.1.2 - 88/11/28 18:16:45
- X * Author : Michael J. Young
- X * USmail : Software Development Technologies, Inc.
- X * 375 Dutton Rd
- X * Sudbury MA 01776
- X * UUCP : harvard!sdti!mjy
- X * Internet : mjy@sdti.SDTI.COM
- X *
- X * =========================================================================
- X * Copyright (C) 1988, Michael J. Young.
- X * Permission is hereby granted to copy and distribute this program for
- X * non-commercial purposes, provided that this notice is not removed.
- X *
- X * This program is being provided "as is", with no warrantee as to safety or
- X * accuracy of results.
- X *
- X * Please send bug reports and enhancements to me at the above address.
- X * =========================================================================
- X */
- X
- X/*
- X * Modification History:
- X *
- X * Wed Nov 23 09:39:01 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
- X * Originated.
- X */
- X
- X#define patch_level 0
- X
- X#include <nlist.h>
- X#include <stdio.h>
- X#include <sys/map.h>
- X#include <sys/param.h>
- X#include <fcntl.h>
- X#include <curses.h>
- X#include <sys/types.h>
- X#include <time.h>
- X#include <varargs.h>
- X#include <signal.h>
- X
- X/*
- X * sizes of the two major allocation maps maintained by the kernel. These
- X * values are actually contained in the linkkit config.h. If that file is
- X * not available, they must be set here.
- X */
- X#ifdef SMAPSIZ
- X# define SMAPSIZE SMAPSIZ
- X#else
- X# define SMAPSIZE 75
- X#endif
- X
- X#ifdef CMAPSIZ
- X# define CMAPSIZE CMAPSIZ
- X#else
- X# define CMAPSIZE 150
- X#endif
- X
- X/*
- X * The following definitions specify the dimensions of the display map.
- X * Change to suit your tastes.
- X */
- X#define MAX_ROWS 20
- X#define MAX_COLUMNS 64
- X#define MAX_ENTRIES (MAX_ROWS*MAX_COLUMNS)
- X
- X/*
- X * the following defines are used to index the namelist array. Their
- X * definitions must be consistent with the order of the namelist array.
- X */
- X#define CORE_MAP 0
- X#define SWAP_MAP 1
- X#define MAX_MEM 2
- X#define N_SWAP 3
- X#define PHYS_MEM 4
- X
- X/*
- X * namelist array : contains a list of names to be extracted from the kernel
- X * image using the nlist function.
- X */
- Xstruct nlist namelist[] = {
- X { "coremap", 0, 0, 0, 0, 0 },
- X { "swapmap", 0, 0, 0, 0, 0 },
- X { "maxmem", 0, 0, 0, 0, 0 },
- X { "nswap", 0, 0, 0, 0, 0 },
- X { "physmem", 0, 0, 0, 0, 0 },
- X { "", 0, 0, 0, 0, 0 }
- X};
- X
- Xstruct map smapbf[SMAPSIZE]; /* local copy of swap allocation map */
- Xstruct map cmapbf[CMAPSIZE]; /* local copy of core allocation map */
- Xint kmaxmem = 0; /* local copy of maxmem */
- Xint kphysmem = 0; /* local copy of physmem */
- Xint knswap = 0; /* local copy of nswap */
- X
- Xint kmem = 0; /* file handle for kernel memory */
- Xint delay = 1; /* seconds between screen updates */
- X
- Xchar dmap[MAX_ENTRIES] = 0; /* display map */
- X
- Xint swap_scale = 1; /* scale factor for swap map display */
- Xint core_scale = 1; /* scale factor for core map display */
- X
- X/*
- X * various useful definitions
- X */
- Xtypedef int boolean;
- X
- X/*#define FALSE 0 /* defined in curses.h */
- X/*#define TRUE 1 /* defined in curses.h */
- X
- X/*
- X * various function declarations
- X */
- Xextern long lseek();
- Xextern int read();
- Xextern time_t time();
- X
- X/*
- X * interface to system error messages
- X */
- Xchar *prog_name = NULL;
- X
- Xextern char *sys_errlist[];
- Xextern int sys_nerr;
- Xextern int errno;
- X
- X/*
- X * error : performs a function similar to perror(3), but supports variable
- X * argument lists. Prints out a formatted error string to stderr, followed if
- X * possible by an appropriate system error message. Control is then
- X * returned to the system with an error status. This function does not
- X * return.
- X */
- X/* VARARGS0 */
- Xvoid error (va_alist)
- Xva_dcl /* varargs */
- X{
- X int err; /* 1st arg - error number */
- X char *str; /* 2nd arg - error format string */
- X va_list args;
- X va_start(args);
- X err = va_arg (args, int);
- X str = va_arg (args, char *);
- X fprintf (stderr, "%s: ", prog_name);
- X vfprintf (stderr, str, args);
- X if (err != 0){
- X if (err <= sys_nerr && err > 0)
- X fprintf (stderr, " : %s\n", sys_errlist[err]);
- X else
- X fprintf (stderr, " : unknown error : %d\n", err);
- X }
- X va_end(args);
- X endwin();
- X exit(1);
- X}
- X
- Xvoid version (){
- X printf ("\nKernel Allocation Map Display\n");
- X printf ("Version : 1.1 - 88/11/28 18:16:45, Patch Level %d\n", patch_level);
- X}
- X
- Xvoid usage(){
- X version();
- X printf ("Usage : map [-[?h]] [-d#]\n\n");
- X printf ("\t-d#\tDelay '#' seconds between screen updates. Defaults\n");
- X printf ("\t\tto 1 second.\n");
- X printf ("\t-h\tDisplays this message.\n");
- X printf ("\t-v\tDisplays version and patch level of program.\n");
- X printf ("\t-?\tDisplays this message.\n");
- X}
- X
- X/*
- X * get_nlist : fetches the required namelist from the kernel image
- X */
- Xvoid get_nlist(){
- X if (nlist ("/unix", namelist) != 0){
- X error (errno, "could not get namelist");
- X }
- X}
- X
- X/*
- X * open_kmem : opens kernel memory
- X */
- Xvoid open_kmem(){
- X
- X /*
- X * open kernel memory
- X */
- X if ((kmem=open ("/dev/kmem", O_RDONLY)) == -1){
- X error (errno, "could not open /dev/kmem");
- X }
- X}
- X
- X/*
- X * init_kmem : reads kernel memory to initialize various static values
- X * that are important for future processing.
- X */
- Xvoid init_kmem (){
- X /*
- X * fetch maxmem (maximum free memory available to a process)
- X */
- X if (lseek (kmem, namelist[MAX_MEM].n_value, 0) != namelist[MAX_MEM].n_value){
- X error (errno, "could not seek maxmem");
- X }
- X if (read (kmem, &kmaxmem, sizeof (int)) != sizeof (int)){
- X error (errno, "could not read maxmem");
- X }
- X
- X /*
- X * fetch physmem (maximum physical memory present in the system)
- X */
- X if (lseek (kmem, namelist[PHYS_MEM].n_value, 0) != namelist[PHYS_MEM].n_value){
- X error (errno, "could not seek physmem");
- X }
- X if (read (kmem, &kphysmem, sizeof (int)) != sizeof (int)){
- X error (errno, "could not read physmem");
- X }
- X
- X /*
- X * fetch nswap (total blocks in the swap device)
- X */
- X if (lseek (kmem, namelist[N_SWAP].n_value, 0) != namelist[N_SWAP].n_value){
- X error (errno, "could not seek nswap");
- X }
- X if (read (kmem, &knswap, sizeof (int)) != sizeof (int)){
- X error (errno, "could not read nswap");
- X }
- X
- X /*
- X * calculate the scale factor for the display maps. The scale
- X * factors should be set in such a way that a single screen can
- X * display the entire map. The scale factors are then massaged to
- X * ensure that they are always even. This is done in multiple
- X * statements to ensure that smart compilers don't optimize the
- X * multiplies and divides away. I'm sure there's a more elegant
- X * and reliable way, but this seems to work.
- X */
- X swap_scale = (knswap + MAX_ENTRIES - 1) / MAX_ENTRIES;
- X swap_scale = (swap_scale + 1) / 2;
- X swap_scale *= 2;
- X core_scale = (kphysmem + MAX_ENTRIES - 1) / MAX_ENTRIES;
- X core_scale = (core_scale + 1) / 2;
- X core_scale *= 2;
- X}
- X
- X/*
- X * read_map : copies the specified kernel allocation map into local memory
- X * for future processing.
- X */
- Xvoid read_map(loc, buf, size)
- Xdaddr_t loc; /* location in kernel to be read */
- Xstruct map *buf; /* buffer in which to place copy */
- Xunsigned size; /* number of map entries to read */
- X{
- X if (lseek (kmem, loc, 0) != loc){
- X error (errno, "could not seek kernel map");
- X }
- X if (read (kmem, buf, size*sizeof (struct map)) != size*sizeof (struct map)){
- X error (errno, "could not read kernel map");
- X }
- X}
- X
- X/*
- X * update_map : modifies all of the appropriate display map cells according
- X * that are affected by the specified kernel allocation map item.
- X */
- Xvoid update_map (dmap, mp, scale)
- Xchar dmap[];
- Xstruct map *mp;
- Xint scale;
- X{
- X int entry;
- X int map_index;
- X int size;
- X size = mp->m_size;
- X for (entry = mp->m_addr; size; entry++){
- X map_index = entry / scale;
- X dmap[map_index] = 0;
- X size--;
- X }
- X}
- X
- X/*
- X * interpret_map : scans through the copy of the kernel allocation map and
- X * updates the specified display map accordingly. The total number of free
- X * blocks in the map are returned.
- X */
- Xint interpret_map(dmap, kmp, scale)
- Xchar dmap[];
- Xstruct map *kmp;
- Xint scale;
- X{
- X int total_free = 0;
- X struct map *mp;
- X memset (dmap, 1, MAX_ENTRIES);
- X for (mp = kmp; mp->m_size; mp++){
- X total_free += mp->m_size;
- X update_map (dmap, mp, scale);
- X }
- X return total_free;
- X}
- X
- X/*
- X * print_map : scans the allocation map, displaying it in the standard
- X * window. Allocated cells are marked with an asterisk ('*'), and free
- X * cells are marked with a period ('.').
- X */
- Xvoid print_map(dmap, scale, total_size)
- Xchar dmap[];
- Xint scale;
- Xlong total_size;
- X{
- X int i, j, k;
- X int entry;
- X move (2,0);
- X for (i = 0; i < MAX_ROWS; i++){
- X k = i*MAX_COLUMNS;
- X if (((long)k*scale) >= total_size)break;
- X printw ("%08lx: ", (long)k * scale);
- X for (j = 0; j < MAX_COLUMNS; j++){
- X if ((((long)k+j)*scale) >= total_size)break;
- X entry = (i*MAX_COLUMNS+j);
- X if (dmap[entry] != 0)addch ('*');
- X else addch ('.');
- X }
- X addch ('\n');
- X }
- X}
- X
- Xvoid interrupt (sig)
- Xint sig;
- X{
- X move (0,0);
- X clrtobot();
- X refresh();
- X endwin();
- X exit(0);
- X}
- X
- X/*
- X * init : performs system and curses initialization
- X */
- Xvoid init (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i;
- X boolean done;
- X char *cp;
- X
- X /*
- X * before we go any further, disable interrupts
- X */
- X signal (SIGINT, SIG_IGN);
- X signal (SIGQUIT, SIG_IGN);
- X signal (SIGHUP, SIG_IGN);
- X signal (SIGTERM, SIG_IGN);
- X
- X /*
- X * save program name for future reference
- X */
- X prog_name = argv[0];
- X
- X for (i = 1; i < argc; i++){
- X cp = argv[i];
- X if (*cp == '-'){
- X done = FALSE;
- X while (*++cp && !done){
- X switch (*cp){
- X
- X case 'd': /* delay */
- X if (cp[1]){
- X delay = atoi (++cp);
- X done = TRUE;
- X }
- X else {
- X delay = atoi (argv[++i]);
- X }
- X break;
- X
- X case 'v': /* display version */
- X version();
- X exit(0);
- X
- X case '?': /* usage */
- X case 'h':
- X usage();
- X exit(0);
- X
- X default:
- X fprintf (stderr, "illegal option : %c; ignored.\n", *cp);
- X break;
- X }
- X }
- X }
- X }
- X
- X /*
- X * curses initialization
- X */
- X initscr();
- X cbreak();
- X noecho();
- X nodelay (stdscr, 1);
- X
- X /*
- X * print out a simple command menu
- X */
- X mvaddch (23, 0, '[');
- X attrset (A_BOLD);
- X addch ('m');
- X attroff (A_BOLD);
- X addch (',');
- X attrset (A_BOLD);
- X addch ('c');
- X attroff (A_BOLD);
- X addstr ("]=memory allocation map [");
- X attrset (A_BOLD);
- X addch ('s');
- X attroff (A_BOLD);
- X addstr ("]=swap allocation map [");
- X attrset (A_BOLD);
- X addch ('q');
- X attroff (A_BOLD);
- X addch (',');
- X attrset (A_BOLD);
- X addch ('x');
- X attroff (A_BOLD);
- X addch (',');
- X attrset (A_BOLD);
- X addch ('e');
- X attrset (A_NORMAL);
- X addstr ("]=exit");
- X
- X /*
- X * now that curses is initialized, catch the interrupt signal
- X * so we can die gracefully
- X */
- X signal (SIGINT, interrupt);
- X signal (SIGQUIT, interrupt);
- X signal (SIGHUP, interrupt);
- X signal (SIGTERM, interrupt);
- X
- X /*
- X * get ready to access kernel memory
- X */
- X open_kmem();
- X get_nlist ();
- X init_kmem();
- X}
- X
- Xint main (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X struct tm *tmbuf; /* to hold current time */
- X time_t tm;
- X boolean done = FALSE; /* will be nonzero when ready to quit */
- X int mem_or_swap = 0; /* 0 = display core map, 1 = swap map */
- X int free = 0; /* free items in allocation map */
- X
- X init (argc, argv);
- X while (!done){
- X
- X /*
- X * get and display current time
- X */
- X time (&tm);
- X tmbuf = localtime (&tm);
- X move (0,0);
- X clrtoeol();
- X mvprintw (0, 67, "%02d:%02d:%02d", tmbuf->tm_hour, tmbuf->tm_min, tmbuf->tm_sec);
- X
- X if (mem_or_swap == 0){
- X
- X /*
- X * update and display core map
- X */
- X read_map (namelist[CORE_MAP].n_value, cmapbf, CMAPSIZE);
- X free = interpret_map (dmap, cmapbf, core_scale);
- X standout();
- X mvaddstr (0, 31, "Memory Allocation");
- X standend();
- X move (1,0);
- X clrtoeol();
- X mvprintw (1, 0, "Total Memory = %ld KBytes, %ld Kernel, %ld Free",
- X ((long)kphysmem*NBPC)/1024,
- X ((long)(kphysmem-kmaxmem)*NBPC)/1024,
- X ((long)free*NBPC)/1024);
- X mvprintw (1, 58, "Scale Factor = %2d", core_scale);
- X print_map (dmap, core_scale*NBPC, (long)kphysmem*NBPC);
- X }
- X else {
- X
- X /*
- X * update and display swap map
- X */
- X read_map (namelist[SWAP_MAP].n_value, smapbf, SMAPSIZE);
- X free = interpret_map (dmap, smapbf, swap_scale);
- X standout();
- X mvaddstr (0, 29, "Swap Device Allocation");
- X standend();
- X move (1,0);
- X clrtoeol();
- X mvprintw (1, 0, "Total swap space = %d Blocks, %d Free", knswap, free);
- X mvprintw (1, 58, "Scale Factor = % d", swap_scale);
- X print_map (dmap, swap_scale, (long)knswap);
- X }
- X
- X /*
- X * refresh the screen and wait a while
- X */
- X refresh();
- X sleep (delay);
- X
- X /*
- X * look for any new commands
- X */
- X switch (getch()){
- X case 'c': /* switch to core (memory) map */
- X case 'm':
- X mem_or_swap = 0;
- X break;
- X
- X case 's': /* switch to swap map */
- X mem_or_swap = 1;
- X break;
- X
- X case 'q': /* quit */
- X case 'e':
- X case 'x':
- X done = TRUE;
- X break;
- X
- X default: /* illegal command, ignore it */
- X break;
- X }
- X
- X }
- X move (0,0);
- X clrtobot();
- X refresh();
- X endwin();
- X}
- X
- END_OF_mapmem.c
- if test 12856 -ne `wc -c <mapmem.c`; then
- echo shar: \"mapmem.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 1 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mike Young
- Software Development Technologies, Inc., Sudbury MA Tel: +1 508 443 5779
- Internet: mjy@sdti.sdti.com UUCP: {harvard,mit-eddie}!sdti!mjy
-